package com.yami.shop.sys.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.yami.shop.security.exception.BadCredentialsExceptionBase;
import com.yami.shop.security.util.SecurityUtils;
import com.yami.shop.sys.model.SysStock;
import com.yami.shop.sys.model.SysStockDetail;
import com.yami.shop.sys.model.SysStockDetailLog;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.SQLReady;
import org.beetl.sql.core.engine.PageQuery;
import org.checkerframework.checker.guieffect.qual.AlwaysSafe;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.github.llyb120.json.Json.cast;
import static com.github.llyb120.json.Json.o;

/**
 * @Author: Administrator
 * @Date: 2020/10/18 16:12
 */
@RequestMapping("/sys/storage")
@RestController
@Transactional
public class StorageController {

    @Autowired
    SQLManager sqlManager;


    @RequestMapping("stockList")
    public Object stockList(){
        return ResponseEntity.ok(sqlManager.lambdaQuery(SysStock.class)
            .select());
    }

    @RequestMapping("saveStock")
    public void saveStock(
        @Validated @RequestBody SysStock sysStock
        ){
        if(StrUtil.isBlank(sysStock.getId())){
            sysStock.setId(IdUtil.objectId());
        }
        sqlManager.upsert(sysStock);
    }

   @RequestMapping ("delStock")
    public void delStock(
        String[] ids
   ){
        sqlManager.lambdaQuery(SysStock.class)
            .andIn(SysStock::getId, Arrays.asList(ids))
            .delete();
    }


    @RequestMapping("findGoods")
    public Object findGoods(
        @RequestParam String id
    ){
       return sqlManager.execute(new SQLReady(String.format("select * from tz_prod where prod_id = '%s'", id)), JSONObject.class);
    }


    /**
     * 入库
     * @return
     */
    @RequestMapping("saveStockDetail")
    public void saveStockDetail(
        @Validated @RequestBody SysStockDetail detail
        ){
        detail.setId(IdUtil.objectId());
        detail.setCreated(new Date());
        sqlManager.upsert(detail);

        log(detail, StockAction.IN);
    }


    @RequestMapping("stockDetailPage")
    public Object stockDetailPage(
        @RequestParam(required = false, defaultValue = "1") int page,
        @RequestParam(required = false, defaultValue = "20") int size,
        String stockId
    ){
        PageQuery<SysStockDetail> pg = sqlManager.lambdaQuery(SysStockDetail.class)
            .andEq(SysStockDetail::getStock_id, stockId)
            .orderBy("created desc")
            .page(page, size);
        return o(
            "list", pg.getList(),
            "total", pg.getTotalRow()
        );
    }

    @RequestMapping("moveStockDetail")
    public void moveStockDetail(
        String id,
        String newStockId
    ){
        SysStockDetail item = sqlManager.lambdaQuery(SysStockDetail.class)
            .andEq(SysStockDetail::getId, id)
            .single();
        if (item == null) {
            throw new BadCredentialsExceptionBase("找不到对应的库存记录") ;
        }
        item.setStock_id(newStockId);
        sqlManager.updateById(item);

        log(item, StockAction.MOVE);
    }


    @RequestMapping("outStockDetail")
    public void outStockDetail(
        String id,
        int num
    ){
        SysStockDetail item = sqlManager.lambdaQuery(SysStockDetail.class)
            .andEq(SysStockDetail::getId, id)
            .single();
        if (item == null) {
            throw new BadCredentialsExceptionBase("找不到对应的库存记录") ;
        }
        if (item.getNum() < num){
            throw new BadCredentialsExceptionBase("没有足够的库存") ;
        }
        item.setNum(item.getNum() - num);
        //如果库存被清0
        if(item.getNum() == 0){
            sqlManager.deleteObject(item);
        } else {
            sqlManager.updateById(item);
        }
        log(item, StockAction.OUT);
    }


    enum StockAction{
        MOVE,
        IN,
        OUT
    }


    @RequestMapping("logPage")
    public Object logPage(
        @RequestParam(required = false, defaultValue = "1") int page,
        @RequestParam(required = false, defaultValue = "20") int size
    ){
        PageQuery<SysStockDetailLog> pg = sqlManager.lambdaQuery(SysStockDetailLog.class)
            .orderBy("created desc")
            .page(page, size);
        return o(
            "list", pg.getList(),
            "total", pg.getTotalRow()
        );
    }

    @Async
    public void log(SysStockDetail detail, StockAction action){
        SysStockDetailLog log = new SysStockDetailLog();
        BeanUtil.copyProperties(detail, log);
        log.setCreated(new Date());
        log.setId(IdUtil.objectId());
        switch (action){
            case IN:
                log.setChange("入库");
                break;

            case OUT:
                log.setChange("出库");
                break;

            case MOVE:
                log.setChange("调拨");
                break;
        }
        log.setDealer(SecurityUtils.getSysUser().getUsername());
        SysStock item = sqlManager.lambdaQuery(SysStock.class)
            .andEq(SysStock::getId, log.getStock_id())
            .single();
        if (item != null) {
            log.setStock_name(item.getName());
        }
        sqlManager.insert(log);
    }

}
